package org.gordonframework.core.tween.interpolate {
	import flash.utils.Dictionary;
	import flash.utils.describeType;	

	/**
	 * @author sampet
	 */
	public class GObjectInterpolator implements GInterpolator {

		private var _name:String;
		private var properties:Dictionary = new Dictionary( );
		private var numProperties:uint = 0;

		public function GObjectInterpolator(target:Object, value:Object, name:String = null) {
			_name = name;
			switch(value.constructor) {
				case Object :				case Array :
					for(var propertyName:String in value) {
						addProperty( target, value, propertyName );
					}
					break;
				default :
					var description:XML = describeType( value );
					var list:XMLList = new XMLList( );
					list += (description.accessor.(@access == "readwrite" && (@type == "Number" || @type == "Object")));					list += (description.variable);
					for each(var node:XML in list) {
						addProperty( target, value, node.@name );
					}
					break;					
			}
		}

		private function addProperty(target:Object, value:Object, name:String):void {
			switch(typeof(value[name])) {
				case "object" :
					properties[name] = new GObjectInterpolator( target[name], value[name], name );
					numProperties++;
					break;
				case "number" :
					properties[name] = new GNumberInterplator( target[name], value[name], name );
					numProperties++;
					break;
			}
		}

		public function get name():String {
			return _name;
		}

		public function interpolate(target:Object, t:Number):void {
			var property:GInterpolator;
			if(name) {
				var propertyTarget:Object = target[name];
				for each(property in properties) {
					property.interpolate( propertyTarget, t );
				}
				target[name] = propertyTarget;				
			} else {
				for each(property in properties) {
					property.interpolate( target, t );
				}
			}
		}

		public function removeProperties(objectInterpolator:GObjectInterpolator):int {
			for each(var property:GInterpolator in objectInterpolator.properties) {
				if(properties[property.name]) {
					if(properties[property.name] is GObjectInterpolator) {
						if(properties[property.name].removeProperties( property ) == 0) {
							delete properties[property.name];
							numProperties--;
						}
					} else {
						delete properties[property.name];
						numProperties--;
					}
				}
			}
			return numProperties;
		}
	}
}
